package com.boyadegroot.divelog.ui.diver;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.boyadegroot.divelog.R;
import com.boyadegroot.divelog.data.DiveLogData;
import com.boyadegroot.divelog.data.DiveLogImport;
import com.boyadegroot.divelog.models.Diver;

import org.xmlpull.v1.XmlPullParserException;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipInputStream;

public class DiverImport extends Fragment {

    private static final String TAG = DiverImport.class.getName();

    private static final int SDE_FILE_REQUEST = 1;

    private Button mChooseSdeFile;
    private Button mStartImport;
    private ProgressBar mProgressBar;
    private CheckBox mOverwriteDataCheckBox;
    private CheckBox mOverwriteSamplesCheckBox;
    private TextView mProgressText;

    private Uri mSdeFileUri;

    private class ImportSdeTask extends AsyncTask<Diver, Integer, Integer> {

        @Override
        protected Integer doInBackground(Diver... divers) {
            long start = System.currentTimeMillis();
            Diver diver = divers[0];
            boolean overwriteData = mOverwriteDataCheckBox.isChecked();
            boolean overwriteSamples = mOverwriteSamplesCheckBox.isChecked();
            Activity activity = getActivity();
            DiveLogImport diveLogImport = new DiveLogImport();
            DiveLogData data = DiveLogData.getInstance(activity);
            ContentResolver resolver = activity.getContentResolver();
            InputStream sdeFileStream;
            try {
                sdeFileStream = resolver.openInputStream(mSdeFileUri);
            } catch (FileNotFoundException e) {
                Log.e(TAG, "File not found: " + mSdeFileUri.getPath());
                cancel(true);
                return 0;
            }
            BufferedInputStream sdeBufferedStream = new BufferedInputStream(sdeFileStream);
            ZipInputStream zipInputStream = new ZipInputStream(sdeBufferedStream);
            int entries = 0;
            try {
                while (zipInputStream.getNextEntry() != null) {
                    if (isCancelled()) {
                        break;
                    }
                    ByteArrayOutputStream zipEntryOutputStream = new ByteArrayOutputStream();
                    byte[] buffer = new byte[1024];
                    int bytesCount;
                    while ((bytesCount = zipInputStream.read(buffer)) != -1) {
                        zipEntryOutputStream.write(buffer, 0, bytesCount);
                    }
                    byte[] zipEntryBytes = zipEntryOutputStream.toByteArray();
                    InputStream zipEntryInputStream = new ByteArrayInputStream(zipEntryBytes);
                    diveLogImport.readDiveXml(data, zipEntryInputStream, diver, overwriteData, overwriteSamples);
                    entries++;
                    publishProgress(entries);
                }
            } catch (IOException e) {
                Log.e(TAG, "Could not read file: " + mSdeFileUri.getPath());
                cancel(true);
            } catch (XmlPullParserException e) {
                Log.e(TAG, "Could not parse file: " + mSdeFileUri.getPath());
                cancel(true);
            }
            if (this.isCancelled()) {
                Log.w(TAG, "Import cancelled after " + ((double) (System.currentTimeMillis() - start) / 1000) + "s");
            } /*else {
                Log.d(TAG, "Import finished in " + ((double) (System.currentTimeMillis() - start) / 1000) + "s");
            }*/
            return entries;
        }

        @Override
        protected void onPostExecute(Integer integer) {
            super.onPostExecute(integer);
            mStartImport.setEnabled(true);
            mChooseSdeFile.setEnabled(true);
            mOverwriteDataCheckBox.setEnabled(true);
            mOverwriteSamplesCheckBox.setEnabled(true);
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mStartImport.setEnabled(false);
            mChooseSdeFile.setEnabled(false);
            mOverwriteDataCheckBox.setEnabled(false);
            mOverwriteSamplesCheckBox.setEnabled(false);
            Activity activity = getActivity();
            ContentResolver resolver = activity.getContentResolver();
            InputStream sdeFileStream;
            try {
                sdeFileStream = resolver.openInputStream(mSdeFileUri);
            } catch (FileNotFoundException e) {
                Log.e(TAG, "File not found: " + mSdeFileUri.getPath());
                cancel(true);
                return;
            }
            BufferedInputStream sdeBufferedStream = new BufferedInputStream(sdeFileStream);
            ZipInputStream zipInputStream = new ZipInputStream(sdeBufferedStream);
            int totalEntries = 0;
            try {
                while (zipInputStream.getNextEntry() != null) {
                    totalEntries++;
                }
            } catch (IOException e) {
                Log.e(TAG, "Could not read file: " + mSdeFileUri.getPath());
                cancel(true);
                return;
            }
            mProgressBar.setProgress(0);
            mProgressBar.setMax(totalEntries);
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            // Log.d(TAG, "Progress: " + values[0] + " of " + mProgressBar.getMax());
            mProgressBar.setProgress(values[0]);
            mProgressText.setText(String.format(
                    getResources().getString(R.string.import_progresstext),
                            values[0],
                            mProgressBar.getMax()));
        }
    }

    public static DiverImport newInstance(Diver diver) {
        DiverImport fragment = new DiverImport();
        Bundle args = new Bundle();
        args.putParcelable("diver", diver);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_import, container, false);
        mChooseSdeFile = (Button) view.findViewById(R.id.choose_sdefile);
        mStartImport = (Button) view.findViewById(R.id.start_import);
        mProgressBar = (ProgressBar) view.findViewById(R.id.importprogess);
        mProgressText = (TextView) view.findViewById(R.id.importprogess_text);
        mOverwriteDataCheckBox = (CheckBox) view.findViewById(R.id.overwrite_data);
        mOverwriteSamplesCheckBox = (CheckBox) view.findViewById(R.id.overwrite_samples);
        mChooseSdeFile.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setType("*/*");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                Activity activity = getActivity();
                PackageManager pm = activity.getPackageManager();
                if (intent.resolveActivity(pm) != null) {
                    startActivityForResult(intent, SDE_FILE_REQUEST);
                }
            }
        });
        View importView = view.findViewById(R.id.start_import);
        importView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Bundle args = getArguments();
                Diver diver = args.getParcelable("diver");
                ImportSdeTask importSdeTask = new ImportSdeTask();
                importSdeTask.execute(diver);
            }
        });
        return view;
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        // Log.v(TAG, "onActivityResult(int requestCode, int resultCode, Intent data)");
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == SDE_FILE_REQUEST) {
            if (resultCode == Activity.RESULT_OK) {
                mSdeFileUri = data.getData();
                mChooseSdeFile.setText(mSdeFileUri.getPath());
                mStartImport.setEnabled(true);
            }
        }
    }
}